package cn.iocoder.yudao.module.famous.doctor.service.casehistory;

import cn.iocoder.yudao.module.famous.doctor.convert.extraction.ExtractionConvert;
import cn.iocoder.yudao.module.famous.doctor.dal.dataobject.extraction.ExtractionDO;
import cn.iocoder.yudao.module.famous.doctor.dal.dataobject.prescription.PrescriptionDO;
import cn.iocoder.yudao.module.famous.doctor.dal.mysql.extraction.ExtractionMapper;
import cn.iocoder.yudao.module.famous.doctor.dal.mysql.prescription.PrescriptionMapper;
import cn.iocoder.yudao.module.famous.doctor.service.prescription.PrescriptionService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.famous.doctor.controller.admin.casehistory.vo.*;
import cn.iocoder.yudao.module.famous.doctor.dal.dataobject.casehistory.CaseHistoryDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.famous.doctor.convert.casehistory.CaseHistoryConvert;
import cn.iocoder.yudao.module.famous.doctor.dal.mysql.casehistory.CaseHistoryMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.setLoginUser;
import static cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder.setTenantId;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.famous.doctor.enums.ErrorCodeConstants.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

/**
 * 我的病历 Service 实现类
 *
 * @author 档案
 */
@Service
@Validated
@Slf4j
public class CaseHistoryServiceImpl implements CaseHistoryService {

    @Resource
    private PrescriptionMapper prescriptionMapper;
    @Resource
    private CaseHistoryMapper caseHistoryMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Resource
    private ExtractionMapper extractionMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createCaseHistory(CaseHistoryCreateReqVO createReqVO) {
        // 插入
        CaseHistoryDO caseHistory = CaseHistoryConvert.INSTANCE.convert(createReqVO);
        caseHistoryMapper.insert(caseHistory);

//        //添加我的开方
//        ExtractionDO extractionDO = new ExtractionDO();
//        BeanUtils.copyProperties(createReqVO, extractionDO);
//        extractionMapper.insert(extractionDO);

        Long tenantId = getLoginUser().getTenantId();
        createReqVO.setTenantId(Math.toIntExact(tenantId));
        createReqVO.setLoginUser(getLoginUser());
        if (createReqVO.getDisposetest()!=null) {
            createReqVO.setDispose(JSON.toJSONString(createReqVO.getDisposetest()));
        }
//        amqpTemplate.convertAndSend("dispose-Queue", JSON.toJSONString(createReqVO)); //公共药房库
        amqpTemplate.convertAndSend("extraction-Queue", JSON.toJSONString(createReqVO));
        // 返回
        return caseHistory.getId();
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("extraction-Queue"),
            exchange = @Exchange("extraction-Exchange")
    ))
    public void extractionreceive(String createReqVO){
        CaseHistoryCreateReqVO caseHistoryCreateReqVO = JSON.parseObject(createReqVO, CaseHistoryCreateReqVO.class);
        setTenantId(Long.valueOf(caseHistoryCreateReqVO.getTenantId()));
        log.info("mq数据:"+ caseHistoryCreateReqVO);
        String dispose = caseHistoryCreateReqVO.getDispose();
        List<Map<String,String>> listObjectSec = JSONArray.parseObject(dispose,List.class);
        //拍照数据 获取病
        String tentativeDiagnosis = caseHistoryCreateReqVO.getTentativeDiagnosis();
        String tentativeDiagnosisfind =null;
        if (tentativeDiagnosis!=null) {
            String[] split = tentativeDiagnosis.split(",");
            tentativeDiagnosisfind=split[0];
        }

        //拍照识别的药方
        List<String> collect = listObjectSec.stream().
                flatMap(map -> map.entrySet().stream())
                .filter(entry -> entry.getKey().equals("name"))
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());
        System.err.println("拍照识别药方:"+collect);

        //数据库  药方数据
//        List<PrescriptionDO> prescriptionContent = caseHistoryMapper.selectPrescriptionContent();
        List<ExtractionDO> prescriptionContent = extractionMapper.selectextractioContent(caseHistoryCreateReqVO.getLoginUser());

        Boolean add=false;
        for (int i = 0; i < prescriptionContent.size(); i++) {
            //数据库中的 用逗号分割
            List<String> split = Arrays.asList(prescriptionContent.get(i).getContent().split(","));
            System.err.println("数据库 药方:"+split);

            List<String> intersection = new ArrayList<>(collect);
            //获取相同数据(交集)数量
            intersection.retainAll(split);
            log.info("获取相同数据(交集)数量 = {}" , intersection.size() );
            if (intersection.size()>=5) {
                List<String> difference = new ArrayList<>(collect);
                difference.removeIf(String::isEmpty);
                //拍照识别药方 新加的药(差集)
                difference.removeAll(split);
                log.info("拍照识别药方 新加的药(差集) = {}" , difference );


                String joinedList = String.join(",", difference);
                String result = prescriptionContent.get(i).getContent() + "," + joinedList;
                log.info("difference逗号拼接 = {}" , result );

                ExtractionDO extractionDO = prescriptionContent.get(i);

                BeanUtils.copyProperties(caseHistoryCreateReqVO,extractionDO);

                List<String> splitillnessLabel = Arrays.asList(prescriptionContent.get(i).getIllnessLabel().split(","));
                if (!splitillnessLabel.contains(tentativeDiagnosisfind) && tentativeDiagnosisfind!=null) {
                    extractionDO.setIllnessLabel(extractionDO.getIllnessLabel()+ "," + tentativeDiagnosisfind);
                }
                extractionDO.setContent(result);
                if(extractionDO.getUseNum()==null && extractionDO.getIllnessNum()==null) {
                    extractionDO.setUseNum(1L);
                    extractionDO.setIllnessNum(1L);
                }else {
                    extractionDO.setUseNum(extractionDO.getUseNum()+1);
                    extractionDO.setIllnessNum(extractionDO.getIllnessNum()+1);
                }


                extractionMapper.updateById(extractionDO);

                add=true;
                break;
            }
        }

        if (!add) {
            ExtractionDO prescriptionDO = new ExtractionDO();
            BeanUtils.copyProperties(caseHistoryCreateReqVO,prescriptionDO);

            String join = String.join(",", collect);
            prescriptionDO.setContent(join);
            if (tentativeDiagnosisfind!=null) {
                prescriptionDO.setIllnessLabel(tentativeDiagnosisfind);
            }
            if(caseHistoryCreateReqVO.getTitle()==null) {
                prescriptionDO.setTitle("需要手动填写药方标题");
            }else {
                prescriptionDO.setTitle(caseHistoryCreateReqVO.getTitle());
            }
            prescriptionDO.setUseNum(1L);
            prescriptionDO.setIllnessNum(1L);
            prescriptionDO.setUsage(caseHistoryCreateReqVO.getUsagetype());
            prescriptionDO.setTenantId(caseHistoryCreateReqVO.getTenantId());
            prescriptionDO.setCreator(String.valueOf(caseHistoryCreateReqVO.getLoginUser().getId()));
            extractionMapper.insert(prescriptionDO);
        }

        log.info("mqReceive = {}" , caseHistoryCreateReqVO );
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("dispose-Queue"),
            exchange = @Exchange("dispose-Exchange")
    ))
    public void receive(String createReqVO){
        CaseHistoryCreateReqVO caseHistoryCreateReqVO = JSON.parseObject(createReqVO, CaseHistoryCreateReqVO.class);
        String dispose = caseHistoryCreateReqVO.getDispose();
        List<Map<String,String>> listObjectSec = JSONArray.parseObject(dispose,List.class);
        //拍照数据 获取病
        String tentativeDiagnosis = caseHistoryCreateReqVO.getTentativeDiagnosis();
        String tentativeDiagnosisfind =null;
        if (tentativeDiagnosis!=null) {
            String[] split = tentativeDiagnosis.split(",");
            tentativeDiagnosisfind=split[0];
        }



        //拍照识别的药方
        List<String> collect = listObjectSec.stream().
                flatMap(map -> map.entrySet().stream())
                .filter(entry -> entry.getKey().equals("name"))
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());
        System.err.println("拍照识别药方:"+collect);

        //数据库  药方数据
        List<PrescriptionDO> prescriptionContent = caseHistoryMapper.selectPrescriptionContent();

        Boolean add=false;
        for (int i = 0; i < prescriptionContent.size(); i++) {
            //数据库中的 用逗号分割
            List<String> split = Arrays.asList(prescriptionContent.get(i).getContent().split(","));
            System.err.println("数据库 药方:"+split);

            List<String> intersection = new ArrayList<>(collect);
            //获取相同数据(交集)数量
            intersection.retainAll(split);
            log.info("获取相同数据(交集)数量 = {}" , intersection.size() );
            if (intersection.size()>=5) {
                List<String> difference = new ArrayList<>(collect);
                difference.removeIf(String::isEmpty);
                //拍照识别药方 新加的药(差集)
                difference.removeAll(split);
                log.info("拍照识别药方 新加的药(差集) = {}" , difference );


                String joinedList = String.join(",", difference);
                String result = prescriptionContent.get(i).getContent() + "," + joinedList;
                log.info("difference逗号拼接 = {}" , result );

                PrescriptionDO prescriptionDO = prescriptionContent.get(i);


                List<String> splitillnessLabel = Arrays.asList(prescriptionContent.get(i).getIllnessLabel().split(","));
                if (!splitillnessLabel.contains(tentativeDiagnosisfind) && tentativeDiagnosisfind!=null) {
                    prescriptionDO.setIllnessLabel(prescriptionDO.getIllnessLabel()+ "," + tentativeDiagnosisfind);
                }
                prescriptionDO.setContent(result);
                if(prescriptionDO.getUseNum()==null) {
                    prescriptionDO.setUseNum(1);
                }else {
                    prescriptionDO.setUseNum(prescriptionDO.getUseNum()+1);
                }
                prescriptionMapper.updateById(prescriptionDO);

                add=true;
                break;
            }
        }


        if (!add) {
                PrescriptionDO prescriptionDO = new PrescriptionDO();
                String join = String.join(",", collect);
                prescriptionDO.setContent(join);
                if (tentativeDiagnosisfind!=null) {
                    prescriptionDO.setIllnessLabel(tentativeDiagnosisfind);
                }
                if(caseHistoryCreateReqVO.getTitle()==null) {
                    prescriptionDO.setTitle("需要手动填写药方标题");
                }else {
                    prescriptionDO.setTitle(caseHistoryCreateReqVO.getTitle());
                }
                prescriptionDO.setUseNum(1);
                prescriptionDO.setTenantId(caseHistoryCreateReqVO.getTenantId());
                prescriptionMapper.insert(prescriptionDO);
        }

        log.info("mqReceive = {}" , caseHistoryCreateReqVO );
    }

    @Override
    public void updateCaseHistory(CaseHistoryUpdateReqVO updateReqVO) {
        // 校验存在
        validateCaseHistoryExists(updateReqVO.getId());
        // 更新
        CaseHistoryDO updateObj = CaseHistoryConvert.INSTANCE.convert(updateReqVO);
        caseHistoryMapper.updateById(updateObj);
    }

    @Override
    public void deleteCaseHistory(Long id) {
        // 校验存在
        validateCaseHistoryExists(id);
        // 删除
        caseHistoryMapper.deleteById(id);
    }

    private void validateCaseHistoryExists(Long id) {
        if (caseHistoryMapper.selectById(id) == null) {
            throw exception(CASE_HISTORY_NOT_EXISTS);
        }
    }

    @Override
    public CaseHistoryDO getCaseHistory(Long id) {
        return caseHistoryMapper.selectById(id);
    }

    @Override
    public List<CaseHistoryDO> getCaseHistoryList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return caseHistoryMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<CaseHistoryDO> getCaseHistoryPage(CaseHistoryPageReqVO pageReqVO) {
        return caseHistoryMapper.selectPage(pageReqVO);
    }

    @Override
    public List<CaseHistoryDO> getCaseHistoryList(CaseHistoryExportReqVO exportReqVO) {
        return caseHistoryMapper.selectList(exportReqVO);
    }

}
